#include <vector>
#include <string>
#include <cassert>

using std::string;
using std::vector;
/**
 * @brief 类模板
 *
 */
namespace cp2
{
    template <typename T>
    class Stack
    {
    private:
        vector<T> elems;

    public:
        Stack(){};
        Stack(T value) { elems.push_back(value); }
        Stack(const Stack &other) { elems = other.elems; };
        void push(const T &elem)
        {
            elems.push_back(elem);
        };
        void pop()
        {
            if (!elems.empty())
                elems.pop_back();
        };
        const T &top() const
        {
            assert(!elems.empty());
            return elems.back();
        };
        bool empty() const
        {
            return elems.empty();
        };

        Stack &operator=(const Stack &other)
        {
            elems = other.elems;
            return *this;
        };
        // 友元
        friend std::ostream &operator<<(std::ostream &strm, const Stack &s)
        {
            for (const T &elem : s.elems)
                strm << elem << " ";
            return strm;
        }
    };

    // 模板特化
    template <>
    class Stack<string>
    {
    private:
        vector<string> elems;

    public:
        Stack(){};
        Stack(const string &value) { elems.push_back(value); }
        Stack(const Stack &other) { elems = other.elems; };
        void push(const string &other)
        {
            elems.push_back(other);
        }
        void pop()
        {
            elems.pop_back();
        }
        const string &top()
        {
            assert(!elems.empty());
            return elems.back();
        }
        bool empty()
        {
            return elems.empty();
        }
        Stack &operator=(const Stack &other)
        {
            elems = other.elems;
            return *this;
        }
        // 友元
        friend std::ostream &operator<<(std::ostream &strm, const Stack &s)
        {
            for (const string &elem : s.elems)
                strm << elem << " ";
            return strm;
        }
    };

    // Stack(const char *) -> Stack<string>;

}